﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
public class ModuleEditor :EditorWindow{
	#region 成员
	bool ISCreateNow;
	string Path_ = Application.dataPath;
	string ModuleRoot = "/Script/Game/Module/";
	string SaveRoot = "/Script/Game/Module/";
	string PathModule{
		get{ 
			return SaveRoot+"Module" + modulename;
		}
	}
	string PathUIView{
		get{ return "/Resources/ViewUI/" + modulename;}
	}
	#endregion
	#region Init
	[MenuItem("Window/模块&ViewUI编辑")]
	static public void Init(){
		ModuleEditor view =  EditorWindow.GetWindow<ModuleEditor> ();
		view.InitPrefab ();
	}
	public void InitPrefab(){
		CreateFile ("/Resources/ModulePrefab");
		AssetDatabase.Refresh ();
		Object root = Resources.Load ("ModulePrefab");
		if (root == null) {
			Debug.Log ("nofind");

			GameObject obj = new GameObject ("UI Root");
			UIRoot _root =  obj.AddComponent<UIRoot> ();
			_root.scalingStyle = UIRoot.Scaling.ConstrainedOnMobiles;
			_root.fitWidth = true;
			_root.fitHeight = false;
			_root.manualWidth = 960;
			GameObject camobj = new GameObject ("UICamera2D");
			camobj.transform.parent = obj.transform;

			Camera cam = camobj.AddComponent<Camera> ();
			cam.clearFlags = CameraClearFlags.Depth;
			cam.orthographic = true;
			cam.orthographicSize = 1;
			cam.nearClipPlane = -10;
			cam.farClipPlane = 10;
			cam.name = "UICamera2D";
			cam.gameObject.AddComponent<UICamera> ();
			//string path = "Assets/Resources/ModulePrefab/UI Root.prefab";
			//SavePrefab (obj, path);
			//GameObject.DestroyImmediate (obj);

		}
	}
	#endregion
	#region
	string[] tools = {"ViewUI编辑","Module编辑"};
	int toolsint;
	public void OnGUI(){
		toolsint = GUILayout.Toolbar (toolsint, tools);
		switch (toolsint) {
		case 0:
			ShowViewMaker();
			break;
		case 1:
			ShowModuleEditor();
			break;
		}
		Repaint ();
	}
	void Update() {
		if(ISCreateNow){
			if(!EditorApplication.isCompiling) {
				Debug.Log ("end");
				ISCreateNow = false;
				coCreate_Preafb();
			}
		}
	}
	#endregion
	#region Module
	string modulename;
	public void ShowModuleEditor(){
		modulename = EditorGUILayout.TextField ("模块名称", modulename);
		if (GUILayout.Button ("创建模块"))
			AddModule ();
	}
	public void AddModule(){

		CreateFile (PathUIView);
		CreateFile (PathModule);
		CreateFile (PathModule+"/Panel");
		CreateFile (PathModule+"/MVC");
		CreateScriptControl ();
//		CreateScriptMain ();
//		CreateScriptView ();
		SaveScene ();

		AssetDatabase.Refresh ();
	}
	#endregion
	#region View 
	List<string> UIDirectorys;
	string[] ModuleDirectorys;
	int selectModule;
	string viewname;
	public void ShowViewMaker(){
		if (GUILayout.Button ("刷新"))
			coModuleGetDir ();
		if (ModuleDirectorys == null || ModuleDirectorys.Length < 0)
			return;
		EditorGUI.BeginDisabledGroup (EditorApplication.isCompiling);
		if (ModuleDirectorys == null || ModuleDirectorys.Length == 0) {
			coModuleGetDir ();
			getViewDirectory();
			if (ModuleDirectorys.Length > selectModule) {
				modulename = ModuleDirectorys [selectModule].Replace ("Module", "");
			}
		
		}
		EditorGUILayout.BeginHorizontal ("box");
		selectModule = EditorGUILayout.Popup (selectModule, ModuleDirectorys);

		EditorGUILayout.EndHorizontal ();
		if (selectModule >= ModuleDirectorys.Length)
			selectModule = 0;
		EditorGUI.BeginDisabledGroup (!ModuleDirectorys [selectModule].Contains ("Module") && ModuleDirectorys [selectModule]!="Base");
		if (GUI.changed) {
			if (selectModule >= ModuleDirectorys.Length)
				selectModule = 0;
			modulename= ModuleDirectorys[selectModule].Replace("Module","");
			getViewDirectory ();
		}
		EditorGUILayout.BeginHorizontal ("box");
		viewname = EditorGUILayout.TextField (viewname);
		EditorGUI.BeginDisabledGroup (viewname == "Module");
		if (GUILayout.Button ("创建")) {
			if(EditorUtility.DisplayDialog("创建界面","创建一个名为"+viewname+"的界面","来吧")){
				loadid =UIDirectorys.Count ;
				coCreateView();
			}
		}
		EditorGUI.EndDisabledGroup ();
		EditorGUILayout.EndHorizontal ();
		if (UIDirectorys != null) {
			if(LoadObj == null)
				loadid = -1;
			for (int i =0; i < UIDirectorys.Count; i++) {
				if(i == loadid)
					GUI.backgroundColor = Color.green;
				else
					GUI.backgroundColor = Color.white;
				EditorGUILayout.BeginHorizontal ("box");
				EditorGUILayout.LabelField (UIDirectorys [i]);
				if(GUILayout.Button("加载",GUILayout.MaxWidth(50))){
					loadid = i;
					viewname = UIDirectorys[i].Split('_')[0];

				   coLoad_Preafb(i);
				}
				EditorGUI.BeginDisabledGroup(loadid != i);
				if(GUILayout.Button("保存",GUILayout.MaxWidth(50)) && loadid == i){
					coSavePrefab();
				}

				EditorGUI.EndDisabledGroup();

				if(GUILayout.Button("打开",GUILayout.MaxWidth(50))){
					OpenScript (i);
				}
				if(GUILayout.Button("删除",GUILayout.MaxWidth(50))){
					if(EditorUtility.DisplayDialog("是否删除界面","删除"+UIDirectorys[i]+"界面","确定")){
						coDele(i);
					}
				}
				EditorGUILayout.EndHorizontal ();

			}
		}
		EditorGUI.EndDisabledGroup ();
		EditorGUI.EndDisabledGroup ();
	}
	#endregion

	#region GTool
	GameObject root;
	GameObject LoadObj;
	int loadid = -1;
	string LoadPath;
	void coCreate_Preafb(){
		GameObject obj;
		obj = GameObject.Find(viewname+"_View");
		GameObject root;
		root = GameObject.Find("UI");
		if(root == null){
			root = ObjManager.Instance.AddChild("ModulePrefab/","UI Root");
			root.name = "UI";
		}
		if(!obj){
			obj = new GameObject(viewname+"_View");
			obj.transform.parent = root.transform;
		}
		
		MyOBJ myobj;
		myobj = obj.GetComponent<MyOBJ>();
		if(myobj == null)
			obj.AddComponent<MyOBJ>();
		string path;
		MonoScript script;
		path = "Assets"+SaveRoot+ModuleDirectorys[selectModule]+"/Panel/" +viewname+"_View"+".cs";
		Debug.Log ("loadScriptPath:  " + path);
		script = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
		System.Type type;
		type = script.GetClass();
		obj.AddComponent(type);
		LoadObj = obj;
		LoadObj.transform.localScale = Vector3.one;
		LoadObj.AddComponent<UIPanel> ();
		LoadObj.layer = LayerMask.NameToLayer ("UI");
		loadid = -1;
		for (int i = 0; i < UIDirectorys.Count; i++) {
			if (UIDirectorys [i] == viewname + "_View") {
				loadid = i;
				break;
			}
		}
		LoadPath = GetPath_Prefab()+viewname+"_View"+".prefab";
		SavePrefab (obj, LoadPath);
		Selection.activeGameObject = obj;
		AssetDatabase.Refresh();
	}
	public void OpenScript(int i){
		string pathview =  "Assets"+SaveRoot+ModuleDirectorys [selectModule]+"/Panel/"+UIDirectorys[i].Split('_')[0]+"_View.cs";
		Debug.Log ("open:" + pathview);
		var script = AssetDatabase.LoadAssetAtPath<MonoScript> (pathview);
		AssetDatabase.OpenAsset (script);
	}
	public void coDele(int i){
		

		string panelname = UIDirectorys[i].Split('_')[0];
		string pathmodule = "Assets"+ModuleRoot+ModuleDirectorys [selectModule];
		string pathview = "Assets/Prefab/ViewUI/"+ModuleDirectorys [selectModule];

		GameObject obj = GameObject.Find (panelname + "_View");
		if (obj != null)
			GameObject.DestroyImmediate (obj);

		DeleFile(pathmodule+"/Panel/"+panelname+"_Control.cs");
		DeleFile(pathmodule+"/Panel/"+panelname+"_Interfcae.cs");
		DeleFile(pathmodule+"/Panel/"+panelname+"_View.cs");
		DeleFile(pathview+"/"+panelname+"_View.prefab");

		AssetDatabase.Refresh ();
		getViewDirectory ();
	}
	
	public void coLoad_Preafb(int i){
		string path = GetPath_Prefab () + viewname + "_View.prefab";
		Debug.Log (path +"<><<<<<<<<<<");
		GameObject  prefab= AssetDatabase.LoadAssetAtPath<GameObject> (path);
			
		LoadObj = GameObject.Instantiate (prefab);
		GameObject root;
		root = GameObject.Find("UI");
		if(root == null){
			root = ObjManager.Instance.AddChild("ModulePrefab/","UI Root");
			root.name = "UI";
		}
		LoadObj.transform.parent = root.transform;
		LoadObj.transform.localPosition = Vector3.zero;
		LoadObj.transform.localEulerAngles = Vector3.zero;
		LoadObj.transform.localScale = Vector3.one;
		Selection.activeTransform = LoadObj.transform;
	}
	public void coSavePrefab(){
		string path = GetPath_Prefab () + viewname + "_View.prefab";
		SavePrefab (LoadObj, path);
		GameObject root;
		root = GameObject.Find("UI");
		if (root != null)
			GameObject.DestroyImmediate (root);
		GameObject manager = GameObject.Find("ObjManager");
		if (manager != null)
			GameObject.DestroyImmediate (manager);
	}
	void SavePrefab(GameObject obj,string localPath){
		
		UnityEngine.Object prefab  = PrefabUtility.CreateEmptyPrefab(localPath);
		PrefabUtility.ReplacePrefab(obj, prefab, ReplacePrefabOptions.ConnectToPrefab);
	}
	string GetPath_Prefab(){
		string s = ModuleDirectorys [selectModule].Replace ("Module","");
		return "Assets/Resources/ViewUI/"+s+"/";
	}
	private void coCreateView(){
		if (viewname.Contains ("_") || viewname.Contains ("View"))
			return;
		else {

			Debug.Log("createFile:"+SaveRoot+ModuleDirectorys[selectModule]+"/Panel");


			CScriptData data = new CScriptData ();

//			string name;
//			///Crete Control
//			name = viewname+"_Control";
//			data.classname = name;
//			data.extend = "ModuleComponent<"+viewname+"_Control>,I"+viewname+"_Control";
//			data.varlist.Add(new CScriptVar(CScriptScope.Private,viewname+"_View","view"));
//			
			CScriptFun fun = new CScriptFun ("Open()",CScriptScope.Public);
//			fun.code.Add ("view = ViewUIMgr.Instance.ShowViewUI<"+viewname+"_View>(ViewUIPanelDepth.BG)");
//			fun.code.Add ("view.Open()");
//			fun.code.Add ("view.AddButtonListener(\"button\",ButtonCallBack)");
//			data.funlist.Add(fun);
//
//			fun = new CScriptFun("ButtonCallBack(GameObject target)",CScriptScope.Public);
//			data.funlist.Add(fun);
//
//			fun = new CScriptFun("Close()",CScriptScope.Public);
//			fun.code.Add("view.Close<"+viewname+"_View>()");
//			data.funlist.Add(fun);
//
//			CreateScript ("/Panel/"+name, data.getData);
//
//
//			string info = "public class F"+viewname+"_Control{"+
//					" \n\t static public I"+viewname+"_Control Create(){ "+
//					"\n\t\t I"+viewname+"_Control control = " + viewname+"_Control.Instance as I"+viewname+"_Control;"+
//					"return control;"+
//					"\n\t}" +
//					"\n}"+
//					"public interface I"+viewname+"_Control{"+
//					"\n\t void Open();"+
//					"\n\t void Close();"+
//					"}";
//			CreateScript("/Panel/"+viewname+"_Interfcae",info);

			data = new CScriptData();

			name = viewname+"_View";
			data.classname = name;
			data.extend = "ViewUI";

			fun = new CScriptFun("Init()",CScriptScope.PublicOverride);
			data.funlist.Add(fun);

			fun = new CScriptFun("Open()",CScriptScope.PublicOverride);
			data.funlist.Add(fun);

			fun = new CScriptFun("Close()",CScriptScope.PublicOverride);
			fun.code.Add("base.OnClose<"+viewname+"_View>();");
			data.funlist.Add(fun);
			CreateScript("/Panel/"+viewname+"_View",data.getData);
			AssetDatabase.Refresh();
			ISCreateNow = true;
			getViewDirectory ();
		}
	}

	private void  coModuleGetDir(){
		try{
			CreateFile(SaveRoot);
		ModuleDirectorys = Directory.GetDirectories(Path_+SaveRoot);
		if(ModuleDirectorys != null ){
			for(var i  = 0;i < ModuleDirectorys.Length;i++){
				ModuleDirectorys[i] = Path.GetFileName(ModuleDirectorys[i]);
			}
		}
		}catch{
		}
	}
	public void getViewDirectory(){
//		List<string> listpath = new List<string>();
		UIDirectorys= new List<string>();
		string[] dir = null;
		try{
			dir = Directory.GetFiles(Path_+ModuleRoot+ModuleDirectorys[selectModule]+"/Panel/");
		}
		catch{}
		if(dir != null){
			for(var i = 0;i < dir.Length;i++){
				string name = Path.GetExtension(dir[i]);
				if(name != ".meta" && dir[i].Contains("View"))
					UIDirectorys.Add(Path.GetFileNameWithoutExtension(dir[i]));
			}
		}
	}
	public void SaveScene(){
		UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.EmptyScene);

		new GameObject (modulename + "Main");
		EditorApplication.SaveScene ("Assets/Scene/"+modulename+".unity");
	}
	public void CreateFile(string path){
		Debug.Log ("path" + path);
		Directory.CreateDirectory (Path_+path);
	}
	public void DeleFile(string path){
		Debug.Log ("DelePath:"+ path);
		AssetDatabase.DeleteAsset(path);
	}
	public void CreateScriptMain(){
		CScriptData data = new CScriptData ();
		string name;
		name = modulename + "Main";
		data.classname = name;
		data.extend = "BaseGameMain";

		CScriptFun fun = new CScriptFun ("InitComponent()",CScriptScope.ProteceedOverride);
		fun.code.Add ("FGameControl.Create(typeof("+ modulename + "Control))");
		fun.code.Add ("FGameView.Create(typeof("+ modulename + "View))");
		fun.code.Add ("FGameModel.Create()");
		fun.code.Add ("base.InitComponent()");
		data.funlist.Add(fun);

		fun = new CScriptFun ("InitModuleName()",CScriptScope.ProteceedOverride);
		fun.code.Add ("BaseModel.Instance.ModueName = \""+modulename+"\";");
		fun.code.Add ("base.InitModuleName()");
		data.funlist.Add(fun);

		CreateScript ("/MVC/"+name, data.getData);
	}
	public void CreateScriptView(){
		CScriptData data = new CScriptData ();
		string name;
		name = modulename + "View";
		data.classname = name;
		data.extend = "BaseView";
		
		CScriptFun fun = new CScriptFun ("Init()",CScriptScope.PublicOverride);
		fun.code.Add ("base.Init()");
		data.funlist.Add(fun);




		
		CreateScript ("/MVC/"+name, data.getData);
	}
	public void CreateScriptControl(){

		CScriptData data = new CScriptData ();
		string name;
		name = modulename + "Control";
		data.classname = name;
		data.extend = "BaseControl";

		CScriptFun fun = new CScriptFun ("Init()",CScriptScope.PublicOverride);
		fun.code.Add ("base.Init()");
		data.funlist.Add(fun);

		fun = new CScriptFun ("InitModuleName()",CScriptScope.ProteceedOverride);
		fun.code.Add ("BaseModel.Instance.ModueName = \""+modulename+"\";");
		fun.code.Add ("base.InitModuleName()");
		data.funlist.Add(fun);

		fun = new CScriptFun ("OnPreLoadBegin()",CScriptScope.PublicOverride);
		fun.code.Add ("//从这里开始添加 配置表无法配置的预加载文件");
		fun.code.Add ("base.OnPreLoadBegin()");
		data.funlist.Add(fun);

		fun = new CScriptFun ("OnPreLoadFinish()",CScriptScope.PublicOverride);
		fun.code.Add ("base.OnPreLoadFinish()");
		data.funlist.Add(fun);

		CreateScript ("/MVC/"+name, data.getData);
	}
	public void CreateScript(string name,string info){
		string path =Path_+ PathModule + name+".cs";
		StreamWriter streamWriter; 
		FileInfo fileInfo = new FileInfo(path);
		streamWriter = fileInfo.CreateText();
		streamWriter.WriteLine(info);  
		streamWriter.Close();
	}

	#endregion
}
#region CodeMaker
public class CScriptData{
	public string classname;
	public string extend;
	public List<string> Using = new List<string> ();
	public List<CScriptVar> varlist = new List<CScriptVar>();
	public List<CScriptFun> funlist = new List<CScriptFun>();
	public CScriptData(){
		Using.Add ("UnityEngine");
		Using.Add ("System.Collections");
	}
	public string getData{
		get{
			string str = "";
			for(int i = 0;i < Using.Count;i++){
				str+= "using "+Using[i]+";"+"\n\r";
			}
			str += "\n\r";
			if(extend!="")
				str += "public class "+classname+" : "+ extend + "{ ";
			else
				str += "public class "+classname + "{ ";
			str += "\n\r";

			for(int i = 0;i < varlist.Count;i++){
				str+= varlist[i].getData()+"\n\r";
			}
			str += "\n\r";
			for(int i = 0;i < funlist.Count;i++){
				str+= funlist[i].getData()+"\n\r";
				str += "\n\r";
			}

			str += "}";
			return str;
		}
	}
}
/// <summary>
/// 作用域
/// </summary>
public enum CScriptScope{
	Public,
	Private,
	PublicOverride,
	Protected,
	PublicVirtual,
	ProtectedVirtual,
	ProteceedOverride,
	StaticPublic,
}
public class CScriptVar{
	public CScriptVar(){}
	public CScriptVar(CScriptScope _scope,string _classname,string _varname){
		scope = _scope;
		classname = _classname;
		varname = _varname;
	}
	public CScriptScope scope;
	public string classname;
	public string varname;
	public string getData(){
		return getScope () + classname + " " + varname +";" ;
	}
	private string getScope(){
		string scopestr = "";
		switch(scope){
		case CScriptScope.Public:
			scopestr = "public ";
			break;
		case CScriptScope.Private:
			scopestr = "private ";
			break;
		case CScriptScope.PublicOverride:
			scopestr = "public override ";
			break;
		case CScriptScope.Protected:
			scopestr = "protected ";
			break;
		case CScriptScope.PublicVirtual:
			scopestr = "public virtual ";
			break;
		case CScriptScope.ProtectedVirtual:
			scopestr = "protected virtual ";
			break;
		case CScriptScope.ProteceedOverride:
			scopestr = "protected override ";
			break;
		case CScriptScope.StaticPublic:
			scopestr = "static public ";
			break;
		}
		return scopestr;
	}
}
public class CScriptFun{
	public CScriptFun(string _name,CScriptScope _scope){
		name = _name;
		scope = _scope;
	}
	public CScriptFun(string _name,CScriptScope _scope,string _back){
		name = _name;
		scope = _scope;
		back = _back;
	}
	public CScriptScope scope;
	public string back = "void";
	public string name = "";
	public List<CScriptVar> varlist = new List<CScriptVar>();
	public List<string> code = new List<string>();
	public string getData(){
		string codestr = getT(1)+getScope () + " " + back + " " + name + "{"+"\n\r"; 
		for (int i = 0; i <varlist.Count; i++) {
			codestr+= getT(2)+ varlist[i].getData()+"\n\r";
		}
		for (int i = 0; i < code.Count; i++) {
			codestr+= getT(2)+code[i]+";"+"\n\r";
		}
		codestr += getT(1)+"}";
		return codestr;
	}
	private string getScope(){
		string scopestr = "";
		switch(scope){
		case CScriptScope.Public:
			scopestr = "public ";
			break;
		case CScriptScope.Private:
			scopestr = "private ";
			break;
		case CScriptScope.PublicOverride:
			scopestr = "public override ";
			break;
		case CScriptScope.Protected:
			scopestr = "protected ";
			break;
		case CScriptScope.PublicVirtual:
			scopestr = "public virtual ";
			break;
		case CScriptScope.ProtectedVirtual:
			scopestr = "protected virtual ";
			break;
		case CScriptScope.ProteceedOverride:
			scopestr = "protected override ";
			break;
		case CScriptScope.StaticPublic:
			scopestr = "static public ";
			break;
		}
		return scopestr;
	}
	public string getT(int count){
		string lab = "";
		for(int i = 0;i < count;i++){
			lab += "\t";
		}
		return lab;
	}
}
#endregion